utils.js ➔ isValid   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
nc 3
nop 2
dl 0
loc 8
rs 9.4285
c 0
b 0
f 0
1
import redis from 'redis'
2
import Limiter from 'ratelimiter'
3
import owasp from 'owasp-password-strength-test'
4
import bcrypt from 'bcrypt-nodejs'
5
import Cookies from 'cookies'
6
import jwt from 'jwt-simple'
7
8
import {
9
  User
10
  ,config
11
  ,coreUtils
12
} from '../../cli'
13
14
export function checkSameEmail(data) {
15
  var emailAlreadyUsed = false
16
  var bdd = User.manager.instance.get()
17
  for (var i = 0, len = bdd.length; i < len; i++) {
18
    var user = bdd[i]
19
    if (user.email === data.email && parseInt(user.id) !== parseInt(data.id)) {
20
      emailAlreadyUsed = true
21
    }
22
  }
23
24
  if (emailAlreadyUsed === true) {
25
    return {
26
      success:0,
27
      message: 'Email adress already exist'
28
    }
29
  }else {
30
    return {
31
      success:1
32
    }
33
  }
34
}
35
36
export function getRole(data) {
37
  var roles = config.users.roles
38
  Array.prototype.forEach.call(roles, (role) => {
39
    if(role.name === data.role) {
40
      data.role = role
41
    }
42
  })
43
44
  return data
45
}
46
47
export function commonPassword(data) {
48
  var owaspConfig = config.users.owasp
49
  owasp.config(owaspConfig)
50
  var sameAsUser = (typeof owaspConfig.sameAsUser !== 'undefined' && owaspConfig.sameAsUser !== null) ? owaspConfig.sameAsUser : true
51
  var mostCommon = (typeof owaspConfig.mostCommon !== 'undefined' && owaspConfig.mostCommon !== null) ? owaspConfig.mostCommon : true
52
  var mostCommonPassword = config.users.mostCommonPassword
53
  owasp.tests.required.push(function(password) {
54
    if (mostCommon && coreUtils.array.contains(mostCommonPassword, password.toLowerCase())) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if mostCommon && coreUtils....password.toLowerCase()) is false. Are you sure this is correct? If so, consider adding return; explicitly.

This check looks for functions where a return statement is found in some execution paths, but not in all.

Consider this little piece of code

function isBig(a) {
    if (a > 5000) {
        return "yes";
    }
}

console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined

The function isBig will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly return undefined.

This behaviour may not be what you had intended. In any case, you can add a return undefined to the other execution path to make the return value explicit.

Loading history...
55
      return 'the password used is too common.'
56
    }
57
  })
58
59
  var currentUserName = data.username
60
  owasp.tests.required.push(function(password) {
61
    var username = currentUserName
62
    var shouldTest = sameAsUser
63
64
    if(shouldTest) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if shouldTest is false. Are you sure this is correct? If so, consider adding return; explicitly.

This check looks for functions where a return statement is found in some execution paths, but not in all.

Consider this little piece of code

function isBig(a) {
    if (a > 5000) {
        return "yes";
    }
}

console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined

The function isBig will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly return undefined.

This behaviour may not be what you had intended. In any case, you can add a return undefined to the other execution path to make the return value explicit.

Loading history...
65
      if (password.toLowerCase() === username.toLowerCase()) {
66
        return 'username and password must be different.'
67
      }
68
      if (password.toLowerCase() === username.toLowerCase().split('').reverse().join('')) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if password.toLowerCase() =...("").reverse().join("") is false. Are you sure this is correct? If so, consider adding return; explicitly.

This check looks for functions where a return statement is found in some execution paths, but not in all.

Consider this little piece of code

function isBig(a) {
    if (a > 5000) {
        return "yes";
    }
}

console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined

The function isBig will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly return undefined.

This behaviour may not be what you had intended. In any case, you can add a return undefined to the other execution path to make the return value explicit.

Loading history...
69
        return 'username and password must be different, not just inverted.'
70
      }
71
    }
72
  })
73
74
  var res = owasp.test(data.password)
75
76
  if(typeof res.errors !== 'undefined' && res.errors !== null
77
      && res.errors.length > 0) {
78
    var message = ''
79
    Array.prototype.forEach.call(res.errors, (error) => {
80
      message += error + '<br />'
81
    })
82
    return {
83
      success:0,
84
      message: message
85
    }
86
  }else {
87
    return {
88
      success:1
89
    }
90
  }
91
}
92
93
export function encryptPassword(numb, password) {
94
  var salt = bcrypt.genSaltSync(numb)
95
  return bcrypt.hashSync(password, salt)
96
}
97
98
export function getUserRoutes(workflow) {
99
  var routes = config.users.routes
100
  var userRoles = []
101
  Array.prototype.forEach.call(Object.keys(routes), (role) => {
102
    if(role === workflow) {
103
      userRoles = routes[role]
104
    }
105
  })
106
107
  return userRoles
108
}
109
110
111
export function findSync(id) {
112
  var bdd = User.manager.instance.get()
113
  for (var i = 0, len = bdd.length; i < len; i++) {
114
    var user = bdd[i]
115
    if (parseInt(user.id) === parseInt(id)) {
116
      return user
117
    }
118
  }
119
  return null
120
}
121
122
export function find(id, done) {
123
  var bdd = User.manager.instance.get()
124
  for (var i = 0, len = bdd.length; i < len; i++) {
125
    var user = bdd[i]
126
    if (parseInt(user.id) === parseInt(id)) {
127
      return done(null, user)
128
    }
129
  }
130
  return done(null, null)
131
}
132
133
export function findByUsername(username, done) {
134
  var bdd = User.manager.instance.get()
135
  for (var i = 0, len = bdd.length; i < len; i++) {
136
    var user = bdd[i]
137
    if (user.username === username) {
138
      return done(null, user)
139
    }
140
  }
141
  return done(null, null)
142
}
143
144
export function findByEmail(email, done) {
145
  var bdd = User.manager.instance.get()
146
  for (var i = 0, len = bdd.length; i < len; i++) {
147
    var user = bdd[i]
148
    if (user.email === email) {
149
      return done(null, user)
150
    }
151
  }
152
  return done(null, null)
153
}
154
155
export function findByResetPasswordToken(resetPasswordToken, done) {
156
  var bdd = User.manager.instance.get()
157
  for (var i = 0, len = bdd.length; i < len; i++) {
158
    var user = bdd[i]
159
    if (user.resetPasswordToken === resetPasswordToken) {
160
      return done(null, user)
161
    }
162
  }
163
  return done(null, null)
164
}
165
166
export function isValid(user, password) {
167
  if(user.actif === 1) {
168
    if(bcrypt.compareSync(password, user.password)) {
169
      return true
170
    }
171
  }
172
  return false
173
}
174
175
export function decodeUser(req, res) {
176
  var decoded = {}
177
  var token = User.utils.getTokenFromCookies(req, res)
178
  if(typeof token !== 'undefined' && token !== null && token !== '') {
179
    try {
180
      var secret = config.users.secret
181
      decoded = jwt.decode(token, secret)
182
    } catch (err) {}
0 ignored issues
show
Coding Style Comprehensibility Best Practice introduced by
Empty catch clauses should be used with caution; consider adding a comment why this is needed.
Loading history...
183
  }
184
185
  return decoded
186
}
187
188
export function getTokenFromCookies(req, res) {
189
  var cookies = new Cookies(req, res, {
190
    secure: config.cookie.secure
191
  })
192
  return cookies.get('x-access-token')
193
}
194
195
export function isAbeRestrictedUrl(currentRoute) {
196
  if( currentRoute.indexOf('/abe/users/forgot') > -1
197
    || currentRoute.indexOf('/abe/users/login') > -1
198
    || currentRoute.indexOf('/abe/users/reset') > -1
199
    || !/^\/abe\//.test(currentRoute)) {
200
    return false
201
  }
202
203
  return true
204
}
205
206
export function isUserAllowedOnRoute(workflow, currentRoute) {
207
  var isAllowed = false
208
209
  if (config.users.enable) {
210
    if( currentRoute.indexOf('/abe/users/forgot') > -1 || currentRoute.indexOf('/abe/users/login') > -1 || !/^\/abe/.test(currentRoute)) {
211
      return true
212
    }
213
214
    if (currentRoute.indexOf('abe/') === -1) {
215
      isAllowed = true
216
    }
217
218
    if (workflow != null) {
219
      var routes = config.users.routes
220
      if(typeof routes[workflow] !== 'undefined' && routes[workflow] !== null) {
221
        Array.prototype.forEach.call(routes[workflow], (route) => {
222
          var reg = new RegExp(route)
223
          if(reg.test(currentRoute)) {
224
            isAllowed = true
225
          }
226
        })
227
      }
228
    }
229
  }else {
230
    isAllowed = true
231
  }
232
  
233
  return isAllowed
234
}
235
236
export function getAll() {
237
  return User.manager.instance.get()
238
}
239
240
export function getUserWorkflow(status) {
241
  var flows = []
242
243
  function addFlow (flow, type, action) {
244
    type = (type != null) ? type : flow
245
    return {
246
      status: flow,
247
      url: `/abe/operations/${action}/${type}`
248
    }
249
  }
250
251
  if (config.users.enable) {
252
    var found = null
253
    Array.prototype.forEach.call(config.users.workflow, (flow) => {
254
255
      if (found != null) {
256
        flows.push(addFlow(flow, flow, 'submit'))
257
        found = null
258
      }
259
260
      if (status == flow) {
261
        found = flow
262
        if (flow != 'draft' && flow != 'publish') {
263
          flows.push(addFlow('reject', flow, 'reject'))
264
        }
265
        if (flow == 'publish') {
266
          flows.push(addFlow('edit', 'draft', 'edit'))
267
        }else {
268
          flows.push(addFlow('save', flow, 'edit'))
269
        }
270
      }
271
    })
272
    if (found != null) {
273
      flows.push(addFlow('save', 'publish', 'submit'))
274
    }
275
  }else {
276
    flows = [addFlow('draft', 'draft', 'submit'), addFlow('publish', 'publish', 'submit')]
277
  }
278
  return flows
279
}
280
281
export function loginLimitTry(username) {
282
  var p = new Promise((resolve) => {
283
    var isNexted = false
284
    try {
285
      var limiterConfig = config.users.limiter
286
287
      var client = redis.createClient()
288
      client.on('error', function() {
289
        if (!isNexted) {
290
          isNexted = true
291
          resolve()
292
        }
293
      })
294
295
      var limit = new Limiter({
296
        id: username,
297
        db: client,
298
        duration: limiterConfig.duration,
299
        max: limiterConfig.max
300
      })
301
302
      limit.get(function(err, limit) {
303
        if (err) {
304
          resolve()
305
        }else {
306
          resolve(limit)
307
        }
308
      })
309
    }catch(e) {
310
      resolve()
311
    }
312
  })
313
314
  return p
315
}